package cn.edu.cug.cs.gtl.docsrv.shp.service.impl;


import cn.edu.cug.cs.gtl.docsrv.Managers;
import cn.edu.cug.cs.gtl.docsrv.dict.exception.BaseException;
import cn.edu.cug.cs.gtl.docsrv.shp.catalog.CatalogTree;
import cn.edu.cug.cs.gtl.docsrv.shp.dao.ShpDao;
import cn.edu.cug.cs.gtl.docsrv.shp.querier.BlockQuerier;
import cn.edu.cug.cs.gtl.docsrv.shp.querier.GeometryQuerier;
import cn.edu.cug.cs.gtl.docsrv.shp.service.ShpService;
import cn.edu.cug.cs.gtl.io.FileDataSplitter;
import cn.edu.cug.cs.gtl.mybatis.mapper.shp.ShpAll;

import cn.edu.cug.cs.gtl.mybatis.mapper.shp.ShpCatalog;
import cn.edu.cug.cs.gtl.mybatis.metadata.ShpUtils;
import cn.edu.cug.cs.gtl.protos.Document;
import cn.edu.cug.cs.gtl.protos.DocumentList;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.util.List;

@Component
public class ShpServiceImpl implements ShpService {

    @Autowired
    ShpDao shpDao;

    public ShpServiceImpl(){super();}

    /**
     * 服务编号：7001
     * 服务名称：addShp
     * 功能描述：单个本地Shp文件入库
     * 接口描述： /api/shp/addShp
     * 传入参数：
     * ShpAll  shp；前端传入ShpAll的JSON对象
     * 返回值：
     * 成功返回true , 否则返回false
     * 调用示例：
     *
     * @param shpAll
     */
    @Override
    public void addShp(ShpAll shpAll) {
        shpDao.addShp(shpAll);
    }

    /**
     * 服务编号：7002
     * 服务名称：addShps
     * 功能描述：多个本地SHP文件入库
     * 接口描述： /api/shp/ addShps
     * 传入参数：
     * List<ShpAll>  shps；前端传入ShpAll列表的JSON对象
     * 返回值：
     * 成功返回true , 否则返回false
     * 调用示例：
     *
     * @param ls
     */
    @Override
    public void addShps(List<ShpAll> ls) {
        shpDao.addShps(ls);
    }

    /**
     * 服务编号：7003
     * 服务名称：addFromRawDB
     * 功能描述：从原始数据库中提取指定类型的图形文件入库
     * 接口描述： /api/shp/addFromRawDB
     * 传入参数：
     * String shpType   图形类型，文件后缀；
     * 返回值：
     * 成功返回true , 否则返回false
     * 调用示例：
     */
    @Deprecated
    @Override
    public boolean addFromRawDB() {
        return shpDao.addFromRawDB();
    }

    /**
     * 服务编号：7004
     * 服务名称：getShpByName
     * 功能描述：图形数据库中提取指定名称的图形文件
     * 接口描述： /api/shp/getShpByName
     * 传入参数：
     * String shpName   图形名称；
     * 返回值：
     * List<ShpAll> shpAllList 的JSON字符串
     * 调用示例：
     *
     * @param shpName
     */
    @Override
    public List<ShpAll> getShpByName(String shpName) {
        return shpDao.getShpByName(shpName);
    }

    /**
     * 服务编号：7005
     * 服务名称：getShpByEnTitle
     * 功能描述：图形数据库中提取指定英文名称的图形文件
     * 接口描述： /api/shp/ getShpByEnTitle
     * 传入参数：
     * String enTitle ；
     * 返回值：
     * List<ShpAll> shpAllList 的JSON字符串
     * 调用示例：
     *
     * @param enTitle
     */
    @Override
    public List<ShpAll> getShpByEnTitle(String enTitle) {
        return shpDao.getShpByEnTitle(enTitle);
    }

    /**
     * 服务编号：7006
     * 服务名称：getShpByCnTitle
     * 功能描述：图形数据库中提取指定中文名称的图形文件
     * 接口描述： /api/shp/ getShpByCnTitle
     * 传入参数：
     * String cnTitle ；
     * 返回值：
     * List<ShpAll> shpAllList 的JSON字符串
     * 调用示例：
     *
     * @param cnTitle
     */
    @Override
    public List<ShpAll> getShpByCnTitle(String cnTitle) {
        return shpDao.getShpByCnTitle(cnTitle);
    }

    /**
     * 服务编号：7007
     * 服务名称：getShpByInternalId
     * 功能描述：图形数据库中提取指定ID的图形文件
     * 接口描述： /api/shp/getShpByInternalId
     * 传入参数：
     * long internalId；
     * 返回值：
     * ShpAll  shp     ; ShpAll的JSON字符串
     * 调用示例：
     *
     * @param internalId
     */
    @Override
    public ShpAll getShpByInternalId(BigDecimal internalId) {
        return shpDao.getShpByInternalId(internalId);
    }

    /**
     * 服务编号：7008
     * 服务名称：getShpByBoundingBox
     * 功能描述：图形数据库中提取指定范围的图形
     * 接口描述： /api/shp/getShpByBoundingBox
     * 传入参数：
     * String bb；//minx,maxx,miny,maxy  数字之间逗号分隔
     * String mask; //intersect 相交的图形； 或  contains 包含的图形
     * 返回值：
     * List<ShpAll> shpAllList 的JSON字符串
     * 调用示例：
     *
     * @param bb
     * @param mask
     */
    @Override
    public List<ShpAll> getShpByBoundingBox(String bb, String mask) {
        if(bb==null || bb.length()<4) return null;
        String [] cs = bb.split(FileDataSplitter.COMMA.getDelimiter());
        double minX = Double.valueOf(cs[0]).doubleValue();
        double maxX = Double.valueOf(cs[1]).doubleValue();
        double minY = Double.valueOf(cs[2]).doubleValue();
        double maxY = Double.valueOf(cs[3]).doubleValue();
        Envelope envelope = new Envelope(minX,maxX,minY,maxY);
        GeometryFactory gf = new GeometryFactory();
        return shpDao.getShpByBoundingBox(gf.toGeometry(envelope),mask);
    }

    /**
     * 服务编号：7009
     * 服务名称：deleteShpByInternalId
     * 功能描述：删除图形数据库中指定ID的图形
     * 接口描述： /api/shp/deleteShpByInternalId
     * 传入参数：
     * long internalId；
     * 返回值：
     * 成功返回true , 否则返回false
     * 调用示例：
     *
     * @param internalId
     */
    @Override
    public boolean deleteShpByInternalId(BigDecimal internalId) {
        return shpDao.deleteShpByInternalId(internalId);
    }

    /**
     * 服务编号：7010
     * 服务名称：getFeatureByBoundingBox
     * 功能描述：图形数据库中提取指定范围的要素
     * 接口描述： /api/shp/getFeatureByBoundingBox
     * 传入参数：
     * String bb；//minx,maxx,miny,maxy  数字之间逗号分隔
     * String mask; //intersect 相交的要素； 或  contains 包含的要素
     * 返回值：
     * FeatureJSON的列表
     * 调用示例：
     *
     * @param bb
     * @param mask
     */
    @Override
    public List<String> getFeatureByBoundingBox(String bb, String mask) {
        if(bb==null || bb.length()<4) return null;
        String [] cs = bb.split(FileDataSplitter.COMMA.getDelimiter());
        double minX = Double.valueOf(cs[0]).doubleValue();
        double maxX = Double.valueOf(cs[1]).doubleValue();
        double minY = Double.valueOf(cs[2]).doubleValue();
        double maxY = Double.valueOf(cs[3]).doubleValue();
        Envelope envelope = new Envelope(minX,maxX,minY,maxY);
        GeometryFactory gf = new GeometryFactory();
        return shpDao.getFeatureByBoundingBox(gf.toGeometry(envelope),mask);
    }

    /**
     * 服务编号：7011
     * 服务名称：getGeometryByBoundingBox
     * 功能描述：图形数据库中提取指定范围的几何对象
     * 接口描述： /api/shp/getGeometryByBoundingBox
     * 传入参数：
     * String bb；//minx,maxx,miny,maxy  数字之间逗号分隔
     * String mask; //intersect 相交的要素； 或  contains 包含的要素
     * 返回值：
     * GeometryJSON的列表
     * 调用示例：
     *
     * @param bb
     * @param mask
     */
    @Override
    public List<String> getGeometryByBoundingBox(String bb, String mask) {
        if(bb==null || bb.length()<4) return null;
        String [] cs = bb.split(FileDataSplitter.COMMA.getDelimiter());
        double minX = Double.valueOf(cs[0]).doubleValue();
        double maxX = Double.valueOf(cs[1]).doubleValue();
        double minY = Double.valueOf(cs[2]).doubleValue();
        double maxY = Double.valueOf(cs[3]).doubleValue();
        Envelope envelope = new Envelope(minX,maxX,minY,maxY);
        GeometryFactory gf = new GeometryFactory();
        return shpDao.getGeometryByBoundingBox(gf.toGeometry(envelope),mask);
    }


    /**
     * 服务编号：7012
     * 服务名称：getGeometriesByShpInternalId
     * 功能描述：图形数据库中提取指定Shp的几何对象
     * 接口描述： /api/shp/getGeometriesByShpInternalId
     * 传入参数：
     * long shpInternalId
     * 返回值：
     * GeometryJSON的列表
     * 调用示例：
     *
     * @param shpInternalId
     */
    @Override
    public List<String> getGeometriesByShpInternalId(BigDecimal shpInternalId) {
        return shpDao.getGeometriesByShpInternalId(shpInternalId);
    }

    /**
     * 服务编号：7013
     * 服务名称：getEnvelopeByShpInternalId
     * 功能描述：图形数据库中提取指定范围的几何对象
     * 接口描述： /api/shp/getEnvelopeByShpInternalId
     * 传入参数：
     * long shpInternalId
     * 返回值：
     * Envelope
     * 调用示例：
     *
     * @param shpInternalId
     */
    @Override
    public Envelope getEnvelopeByShpInternalId(BigDecimal shpInternalId) {
        return shpDao.getEnvelopeByShpInternalId(shpInternalId);
    }

    /**
     * 服务编号：7014
     * 服务名称：getShpCatalogs
     * 功能描述：图形数据库中提取所有分类
     * 接口描述： /api/shp/getShpCatalogs
     * 传入参数：
     * 返回值：
     * List<ShpCatalog> catalogs
     * 调用示例：
     */
    @Override
    public List<ShpCatalog> getShpCatalogs() {
        return shpDao.getShpCatalogs();
    }

    /**
     * 服务编号：7015
     * 服务名称：getGeometriesByShpInternalId
     * 功能描述：图形数据库中提取指定Shp的几何对象
     * 接口描述： /api/shp/getFeaturesByShpInternalId
     * 传入参数：
     * long shpInternalId
     * 返回值：
     * FeatureJSON的列表
     * 调用示例：
     *
     * @param shpInternalId
     */
    @Override
    public List<String> getFeaturesByShpInternalId(BigDecimal shpInternalId) {
        return shpDao.getFeaturesByShpInternalId(shpInternalId);
    }

    /**
     服务编号：7016
     服务名称：getDocumentByShpInternalId
     功能描述：图形数据库中提取指定Shp文档
     接口描述： /api/shp/getDocumentByShpInternalId
     传入参数：
     long shpInternalId
     返回值：
     Document doc;
     其中，每个Feature的GeoJSON字符串为Document的一个content；
     其他的不为空的字段为该Shp文档的元数据。
     调用示例：
     http://localhost:8090/api/shp/getDocumentByShpInternalId?shpInternalId=3
     */
    @Override
    public Document getDocumentByShpInternalId( BigDecimal shpInternalId){
        try {
            return   shpDao.getDocumentByShpInternalId(shpInternalId);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * 服务编号：7023
     * 服务名称：getDocumentsByCatalogInternalId
     * 功能描述：图形数据库中提取指定分类ID的所有图形文档
     * 接口描述：/api/shp/getDocumentsByCatalogInternalId
     * 传入参数：
     * long catalogInternalId
     * 返回值：
     * DocumentList docList;
     * 其中，每个Feature的GeoJSON字符串为Document的一个content；
     * 其他的不为空的字段为该Shp文档的元数据。
     * 调用示例：
     * http://localhost:8090/api/shp/getDocumentsByCatalogInternalId?catalogInternalId=3
     *
     * @param catalogInternalId
     */
    @Override
    public DocumentList getDocumentsByCatalogInternalId(BigDecimal catalogInternalId) {
        try {
            try {
                List<ShpAll> shpAllList= shpDao.getShpByCatalogInternalId(catalogInternalId);
                if(shpAllList!=null) {
                    DocumentList.Builder documentListBuilder = DocumentList.newBuilder();
                    for (ShpAll shpAll : shpAllList) {
                        Document doc = ShpUtils.convert(shpAll);
                        documentListBuilder.addElement(doc);
                    }
                    return documentListBuilder.build();
                }
                else
                    return null;
            } catch (Exception e) {
                throw new BaseException(e.getMessage());
            }
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * 将所有的目录整理成一个树后返回
     *
     * @return
     */
    @Override
    public CatalogTree getCatalogTree() {
        return shpDao.getCatalogTree();
    }

    @Override
    public List<BigDecimal> getShpInternalIdsByCatalogInternalId(BigDecimal catalogId) {
        return shpDao.getShpInternalIdsByCatalogInternalId(catalogId);
    }

//
//    @Override
//    public List<ShpItem> getShpData() throws Exception {
//        return shpDao.getShpData();
//    }
//
//    @Override
//    public List<ShpAll> getShpDataAll() throws Exception {
//        return shpDao.getShpDataAll();
//    }
//
//    @Override
//    public List<ShpAll> queryShpData(ShpAll shpAll) throws Exception {
//        return shpDao.queryShpData(shpAll);
//    }
//
//    @Override
//    public void addShpData(ShpAll shpAll) throws Exception {
//        shpDao.addShpData(shpAll);
//    }
//
//    @Override
//    public void deleteShpData(ShpAll shpAll) throws Exception {
//        shpDao.deleteShpData(shpAll);
//    }
//
//    @Override
//    public void updateShpData(ShpAll shpAll) throws Exception {
//        shpDao.updateShpData(shpAll);
//    }
//
//    @Override
//    public void downloadShpFile(BigDecimal shpInternalId, HttpServletResponse response) throws Exception {
//        ServletOutputStream outputStream = null;
//        InputStream inputStream = null;
//        try {
//            outputStream = response.getOutputStream();
//            inputStream = shpDao.downloadShpFile(shpInternalId);
//            byte[] buffer = new byte[2048];
//            int len;
//            while ((len = inputStream.read(buffer)) != -1) {
//                outputStream.write(buffer, 0, len);
//            }
//        } finally {
//            if (inputStream != null){
//                inputStream.close();
//            }
//            if (outputStream != null) {
//                outputStream.close();
//            }
//        }
//    }
}
